# -*- awk -*-
# eotk (c) 2017 Alec Muffett

# EMACS awk mode works quite well for nginx configs

# **HARD** configuration
# aggressively swap domain names for onions, with whitelisted exceptions...

# logs and pids
pid %PROJECT_DIR%/nginx.pid;
error_log %LOG_DIR%/nginx-error.log %NGINX_SYSLOG%;

# TODO: notes for custom 403 error-handling pages:
# https://www.cyberciti.biz/faq/unix-linux-nginx-custom-error-403-page-configuration/
# https://nginx.org/en/docs/http/ngx_http_core_module.html#error_page

# performance
%%IF %IS_SOFTMAP%
worker_processes %SOFTMAP_NGINX_WORKERS%; # softmap
%%ELSE
worker_processes %NGINX_WORKERS%; # hardmap
%%ENDIF
worker_rlimit_nofile %NGINX_RLIM%;
events {
  worker_connections %NGINX_RLIM%;
}

http {
  # nginx fails without large enough buckets (sigh)
  map_hash_bucket_size %NGINX_HASH_BUCKET_SIZE%;

  # dns for proxy (sigh)
  # we should do `ipv6=off` here, but compat issues, hence NGINX_RESOLVER_FLAGS
  resolver %NGINX_RESOLVER% valid=%NGINX_TIMEOUT%s %NGINX_RESOLVER_FLAGS%;
  resolver_timeout %NGINX_TIMEOUT%s;

  # we walk a line between keeping it small and flooding resources...
  proxy_buffering on;

  # for initial; impacts SSL header
  proxy_buffer_size %NGINX_BLOCK_SIZE%;

  # for rest of response
  proxy_buffers %NGINX_BLOCK_COUNT% %NGINX_BLOCK_SIZE%;

  # how much can be busy sending to client?
  proxy_busy_buffers_size %NGINX_BLOCK_BUSY_SIZE%;

  # where to stash oversize requests?
  client_body_temp_path /tmp/nginx-body-%PROJECT%;
  client_max_body_size 4m;

  # in case we want to start spooling responses locally
  proxy_temp_path /tmp/nginx-proxy-%PROJECT%;
  proxy_max_temp_file_size %NGINX_TMPFILE_SIZE%;
  proxy_temp_file_write_size %NGINX_BLOCK_SIZE%;

  %%IF %NGINX_CACHE_SECONDS%
  # nginx caching static responses for %NGINX_CACHE_SECONDS% seconds
  # - this is a lightweight cache to reduce "storms", hence the global
  # approch of "cache everything for a small number of seconds"
  # https://nginx.org/en/docs/http/ngx_http_proxy_module.html
  proxy_cache_path /tmp/nginx-cache-%PROJECT% levels=1:2 keys_zone=%PROJECT%:%NGINX_CACHE_SIZE%;
  proxy_cache %PROJECT%;
  proxy_cache_min_uses %NGINX_CACHE_MIN_USES%;
  proxy_cache_revalidate on;
  proxy_cache_use_stale timeout updating;
  proxy_cache_valid any %NGINX_CACHE_SECONDS%s; # "any" includes 404s, etc

  # content-types to not cache
  map $http_content_type $no_cache_content_type {
    %%CSV %NO_CACHE_CONTENT_TYPE%
    %1% 1;
    %%ENDCSV
    default 0;
  }

  # hosts not to cache
  map $http_host $no_cache_host {
    hostnames;
    %%CSV %NO_CACHE_HOST%
    %1% 1;
    %%ENDCSV
    default 0;
  }

  # so, should we skip caching this stuff for some reason?
  proxy_no_cache $no_cache_content_type $no_cache_host;
  proxy_cache_bypass $no_cache_content_type $no_cache_host;
  %%ELSE
  # nginx caching disabled
  %%ENDIF

  # logs
  access_log %LOG_DIR%/nginx-access.log;

  # global settings
  server_tokens off;

  # allow/deny (first wins)
  allow "unix:";
  deny all;

  # rewrite these content types; text/html is implicit
  subs_filter_types
  application/javascript
  application/json
  application/x-javascript
  text/css
  text/javascript
  text/xml
  ;

  %%IF %PRESERVE_CSV%
  # preserve subs (save-phase): 1=description,2=re,3=i_or_empty,4=replacement
  %%CSV %PRESERVE_CSV%
  # saving regexp '%2%' as '%1%' for replacement with '%4%' (%3%)
  subs_filter
  (%PRESERVE_PREAMBLE%)(%2%)\\b
  $1%PRESERVE_COOKIE%%1%%PRESERVE_COOKIE%
  g%3%r
  ;
  %%ENDCSV
  %%ELSE
  # no preserve subs (save-phase)
  %%ENDIF

  %%BEGIN
  # for %DNS_DOMAIN% -> %ONION_ADDRESS%
  subs_filter
  \\b%DNS_DOMAIN_RE2%\\b
  %ONION_ADDRESS%
  gir
  ;

  %%END

  %%IF %FOREIGNMAP_CSV%
  # foreignmap subs: 1=onion,2=re,3=re2,4=dns,5=re,6=re2
  %%CSV %FOREIGNMAP_CSV%
  # for %4% -> %1%
  subs_filter
  \\b%6%\\b
  %1%
  gir
  ;
  %%ENDCSV
  %%ELSE
  # no foreignmap subs
  %%ENDIF

  %%IF %PRESERVE_CSV%
  # preserve subs (restore-phase): 1=description,2=re,3=i_or_empty,4=replacement
  %%CSV %PRESERVE_CSV%
  # restoring '%1%' with '%4%'
  subs_filter
  %PRESERVE_COOKIE%%1%%PRESERVE_COOKIE%
  %4%
  g
  ;
  %%ENDCSV
  %%ELSE
  # no preserve subs (restore-phase)
  %%ENDIF

  # fix the cookies
  %%BEGIN
  proxy_cookie_domain
  ~^(.*?)\\b%DNS_DOMAIN_RE2%$
  $1%ONION_ADDRESS%
  ;
  %%END

  # fix the header-redirects
  %%BEGIN
  proxy_redirect
  ~*^(.*?)\\b%DNS_DOMAIN_RE2%\\b(.*)$
  $1%ONION_ADDRESS%$2
  ;
  %%END

  # o_to_d_lookup -> if cannot remap, return input.  note: old versions
  # of lua-plugin cannot cope with code like o_to_d_mappings[o[1]]
  # because of `long bracket syntax`; the `[o[` freaks it out.
  # See: https://github.com/openresty/lua-nginx-module/issues/748
  init_by_lua_block {
    -- helper functions for elsewhere

    slog = function (s) -- in case of manual debugging
      ngx.log(ngx.ERR, s)
      return
    end

    has_suffix = function (s, x)
      return string.sub(s, -string.len(x)) == x
    end

    -- mapping onions to dns

    o_to_d_mappings = {}
    %%BEGIN
    o_to_d_mappings["%ONION_ADDRESS%"] = "%DNS_DOMAIN%"
    %%END

    o_to_d_lookup = function (m)
      local k = m[1] -- see note above re: array syntax
      return ( o_to_d_mappings[k] or k )
    end

    onion_to_dns = function (i)
      if i == nil or i == "" then
        return i
      end
      local o, num, errs = ngx.re.gsub(i, "\\b([a-z2-7]{16}\\.onion)\\b", o_to_d_lookup, "io")
      return o
    end

    -- mapping dns to onions, for experimentation

    d_to_o_mappings = {}
    %%BEGIN
    d_to_o_mappings["%DNS_DOMAIN%"] = "%ONION_ADDRESS%"
    %%END

    d_to_o_lookup = function (m)
      local k = m[1] -- see note above re: array syntax
      return ( d_to_o_mappings[k] or k )
    end

    dns_to_onion = function (i)
      local num, errs
      %%BEGIN
      i, num, errs = ngx.re.gsub(i, "\\b%DNS_DOMAIN_RE2%\\b", "%ONION_ADDRESS%", "io")
      %%END
      return i
    end

    -- a note for future maintainers; if we were being strictly orthogonal then
    -- the replacement with ONION_ADDRESS in much of this Lua block would have to
    -- be double-escaped for potential backslashes, because double-quotes;
    -- however this is not needed because DNS forbids backslash; the only code
    -- where this becomes evident/necessary is here, with "_RE2":

    dnsre_to_onionre = function (i)
      local num, errs
      %%BEGIN
      i, num, errs = ngx.re.gsub(i, "\\b%DNS_DOMAIN_RERE2%\\b", "%ONION_ADDRESS_RE2%", "io")
      %%END
      return i
    end
  }

  # filter the response headers en-route back to the user
  header_filter_by_lua_block {
    local k, v

    -- rewrite cors/acao
    k = "Access-Control-Allow-Origin"
    v = ngx.header[k]
    if v and v ~= "*" then
      ngx.header[k] = dns_to_onion(v)
    end

    %%IF %SUPPRESS_HEADER_CSP%
    -- csp suppressed, no rewrite needed
    %%ELSE
    -- rewrite csp
    k = "Content-Security-Policy"
    v = ngx.header[k]
    if v then
      ngx.header[k] = dns_to_onion(v)
    end

    -- rewrite csp (report-only)
    k = "Content-Security-Policy-Report-Only"
    v = ngx.header[k]
    if v then
      ngx.header[k] = dns_to_onion(v)
    end
    %%ENDIF
  }

  # filter the response body en-route back to the user
  body_filter_by_lua_block {
    %%IF %DEBUG_TRAP%
    -- debug traps
    local i = ngx.arg[1]
    local ct = ngx.header["Content-Type"]
    local uri = ngx.var.uri
    local iterator, err
    %%CSV %DEBUG_TRAP%
    iterator, err = ngx.re.gmatch(i, ".{0,32}(%1%).{0,32}")
    if not iterator then
      ngx.log(ngx.ERR, "gmatch error: ", err)
    else
      while true do
        local m, err = iterator()
        if err then
          ngx.log(ngx.ERR, "iterator error: ", err)
          break
        end
        if not m then
          break
        end
        slog(string.format("TRAP <<%s>> CONTEXT <<%s>> TYPE <<%s>> URI %s", m[1], m[0], ct, uri))
      end -- while true
    end -- if iterator
    %%ENDCSV
    %%ELSE
    -- no debug traps
    %%ENDIF
  }

  %%IF %SUPPRESS_HEADER_CSP%
  # csp suppression
  proxy_hide_header "Content-Security-Policy";
  proxy_hide_header "Content-Security-Policy-Report-Only";
  %%ELSE
  # csp not suppressed, will be rewritten instead, see below
  %%ENDIF

  %%IF %SUPPRESS_HEADER_HSTS%
  # hsts suppression
  proxy_hide_header "Strict-Transport-Security";
  %%ELSE
  # hsts not suppressed
  %%ENDIF

  %%IF %SUPPRESS_HEADER_HPKP%
  # hpkp suppression
  proxy_hide_header "Public-Key-Pins";
  proxy_hide_header "Public-Key-Pins-Report-Only";
  %%ELSE
  # hpkp not suppressed
  %%ENDIF

  # global proxy settings
  proxy_read_timeout %NGINX_TIMEOUT%;
  proxy_connect_timeout %NGINX_TIMEOUT%;

  # SSL config
  ssl_certificate %SSL_DIR%/%CERT_PREFIX%.cert;
  ssl_certificate_key %SSL_DIR%/%CERT_PREFIX%.pem;
  ssl_buffer_size 4k;
  #ssl_ciphers 'EECDH+CHACHA20:EECDH+AESGCM:EECDH+AES256'; ## LibreSSL, OpenSSL 1.1.0+
  ssl_ciphers 'EECDH+AESGCM:EECDH+AES256'; ## OpenSSL 1.0.1% to 1.0.2%
  ssl_ecdh_curve prime256v1;
  #ssl_ecdh_curve secp384r1:prime256v1; ## NGINX nginx 1.11.0 and later
  ssl_prefer_server_ciphers on;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;

  # websockets: on the basis of http_upgrade, set connection_upgrade:
  # empty -> empty
  # default -> "upgrade"
  map $http_upgrade $connection_upgrade {
    default "upgrade";
    "" "";
  }

  %%BEGIN
  %%IF %FORCE_HTTPS%
  # FORCE_HTTPS is in use; set up separate server for port 80 & force redirects
  server {
    %%IF %IS_SOFTMAP%
    %%RANGE I 1 %SOFTMAP_TOR_WORKERS%
    listen unix:%PROJECT_DIR%/%TOR_WORKER_PREFIX%-%I%.d/port-80.sock;
    %%ENDRANGE
    %%ELSE
    listen unix:%PROJECT_DIR%/%ONION_ADDRESS%.d/port-80.sock;
    %%ENDIF

    # subdomain regexp captures trailing dot, use carefully; does not need "~*"
    # NB: this regexp should be kept in-sync with the other FORCE_HTTPS copy
    server_name
    %ONION_ADDRESS%
    ~^(?<servernamesubdomain>([-0-9a-z]+\\.)+)%ONION_ADDRESS_RE2%$
    ;

    %%IF %COOKIE_LOCK%
    # if we are visiting the magic path, issue a cookie immediately
    location "%COOKIE_LOCK%" {
      add_header Set-Cookie "eotk_lock=%COOKIE_LOCK%;Domain=.%ONION_ADDRESS%;Path=/;Max-Age=604800";
      return 200 "OK";
    }
    %%ELSE
    # no cookie_lock cookie setting
    %%ENDIF

    %%IF %SUPPRESS_TOR2WEB%
    # suppress tor2web traffic; "let them use clearnet"
    if ( $http_x_tor2web ) {
      return 403 "%BLOCK_ERR%";
    }
    %%ELSE
    # tor2web not suppressed
    %%ENDIF

    # tell the client to try again as HTTPS without ever leaving the onion
    # use 307 / temporary redirect because your URIs may change in future
    # use $host (not $server) to copy-over subdomains, etc, transparently
    return 307 https://$host$request_uri;
  }
  %%ELSE
  # FORCE_HTTPS is not in use, cleartext data may traverse the internet
  %%ENDIF

  # for %ONION_ADDRESS% -> %DNS_DOMAIN%
  server {
    %%IF %IS_SOFTMAP%
    %%RANGE I 1 %SOFTMAP_TOR_WORKERS%
    %%IF not %FORCE_HTTPS%
    # FORCE_HTTPS is not in use, cleartext data may traverse the internet
    listen unix:%PROJECT_DIR%/%TOR_WORKER_PREFIX%-%I%.d/port-80.sock;
    %%ENDIF
    listen unix:%PROJECT_DIR%/%TOR_WORKER_PREFIX%-%I%.d/port-443.sock ssl;
    %%ENDRANGE
    %%ELSE
    # hardmap
    # unix sockets; use <ONION_ADDRESS>.d as a naming convention
    %%IF not %FORCE_HTTPS%
    # FORCE_HTTPS is not in use, cleartext data may traverse the internet
    listen unix:%PROJECT_DIR%/%ONION_ADDRESS%.d/port-80.sock;
    %%ENDIF
    listen unix:%PROJECT_DIR%/%ONION_ADDRESS%.d/port-443.sock ssl;
    %%ENDIF

    # subdomain regexp captures trailing dot, use carefully; does not need "~*"
    # NB: this regexp should be kept in-sync with the other FORCE_HTTPS copy
    server_name
    %ONION_ADDRESS%
    ~^(?<servernamesubdomain>([-0-9a-z]+\\.)+)%ONION_ADDRESS_RE2%$
    ;

    %%IF %COOKIE_LOCK%
    # if we are visiting the magic path, issue a cookie immediately
    location "%COOKIE_LOCK%" {
      add_header Set-Cookie "eotk_lock=%COOKIE_LOCK%;Domain=.%ONION_ADDRESS%;Path=/;Max-Age=604800";
      return 200 "OK";
    }
    %%ELSE
    # no cookie_lock cookie setting
    %%ENDIF

    %%IF %SUPPRESS_TOR2WEB%
    # suppress tor2web traffic; "let them use clearnet"
    if ( $http_x_tor2web ) {
      return 403 "%BLOCK_ERR%";
    }
    %%ELSE
    # tor2web not suppressed
    %%ENDIF

    %%IF %BLOCK_HOST%
    # politely block hosts matching this name
    %%CSV %BLOCK_HOST%
    if ( $host = "%0%" ) {
      return 403 "%BLOCK_ERR%";
    }
    %%ENDCSV
    %%ELSE
    # no polite named host blocking
    %%ENDIF

    %%IF %BLOCK_HOST_RE%
    # politely block hosts matching this regular expression
    %%CSV %BLOCK_HOST_RE%
    if ( $host ~* "%0%" ) {
      return 403 "%BLOCK_ERR%";
    }
    %%ENDCSV
    %%ELSE
    # no polite regular expression host blocking
    %%ENDIF

    %%IF %BLOCK_LOCATION%
    # politely block locations by name
    %%CSV %BLOCK_LOCATION%
    location %0% {
      return 403 "%BLOCK_ERR%";
    }
    %%ENDCSV
    %%ELSE
    # no polite named location blocking
    %%ENDIF

    %%IF %BLOCK_LOCATION_RE%
    # politely block locations matching this regular expression
    %%CSV %BLOCK_LOCATION_RE%
    location ~* "%0%" {
      return 403 "%BLOCK_ERR%";
    }
    %%ENDCSV
    %%ELSE
    # no polite regular expression location blocking
    %%ENDIF

    %%IF %REDIRECT_HOST_CSV%
    # redirect_hosts: 1=host_re,2=scheme://host.dom,3=code
    %%CSV %REDIRECT_HOST_CSV%
    if ( $host ~* "%1%" ) {
      return %3% %2%$request_uri;
    }
    %%ENDCSV
    %%ELSE
    # no redirect_hosts
    %%ENDIF

    %%IF %REDIRECT_LOCATION_CSV%
    # redirect_locations: 1=location_re,2=scheme://host.dom,3=code
    %%CSV %REDIRECT_LOCATION_CSV%
    location ~* "%1%" {
      return %3% %2%$request_uri;
    }
    %%ENDCSV
    %%ELSE
    # no redirect_locations
    %%ENDIF

    %%IF %NGINX_HELLO_ONION%
    # for test & to help SSL certificate acceptance
    location ~* ^/hello[-_]onion/?$ {
      return 200 "Hello, Onion User!";
    }
    %%ELSE
    # no "hello-onion" endpoint
    %%ENDIF

    %%IF %HARDCODED_ENDPOINT_CSV%
    # hardcoded_endpoints: 1=path_re,2=response
    %%CSV %HARDCODED_ENDPOINT_CSV%
    location ~* %1% {
      return 200 %2%;
    }
    %%ENDCSV
    %%ELSE
    # no hardcoded_endpoints
    %%ENDIF

    %%IF %PATHS_CONTAIN_ONIONS%
    # URI paths may contain onionified hostnames which need rewriting
    # before passing upwards to the origin; this is a consequence of
    # "hard-mode" brute-force rewriting, and needs gentle unpicking:
    set $deonionified_uri '';
    # There is an irreducible problem: what if the URI origin path
    # *literally* includes the name of one of our onions? Well, it
    # will be re-written to the corresponding DNS domain name. This is
    # a small price to pay for the benefits of "hard-mode" rewrites on
    # complex websites, but we can reduce the pain a tiny bit by
    # making the in-path comparisons case-sensitive to lowercase, and
    # document the issue with that workaround
    if ( $uri ~ "\\.onion" ) { # cheapest, static, case-sensitive test, here...
      set_by_lua_block $deonionified_uri {
        local old_uri = ngx.var.uri
        -- more expensive case-sensitive test, here...
        local m, err = ngx.re.match(old_uri, "\\b[a-z2-7]{16}\\.onion\\b", "o")
        if not m then
          return "" -- nothing to attempt to rewrite, quick return
        end
        -- attempt rewrites (function is case-insensitive, hence...)
        local new_uri = onion_to_dns(old_uri)
        if new_uri == old_uri then -- nothing changed, quick return
          return ""
        end
        return new_uri
      }
    }
    if ( $deonionified_uri ) {
      set $new_uri $deonionified_uri; # swap
      set $deonionified_uri ''; # prevent revisiting
      rewrite ^ $new_uri last;
    }
    %%ELSE
    # paths are assumed not to contain onionified hostnames
    %%ENDIF

    # blacklists

    %%IF %USER_AGENT_BLACKLIST_RE%
    # check user_agent_blacklist_re
    %%CSV %USER_AGENT_BLACKLIST_RE%
    if ( $http_user_agent ~* "%0%" ) {
      %NGINX_ACTION_ABORT%;
    }
    %%ENDCSV
    %%ELSE
    # no user_agent_blacklist_re
    %%ENDIF

    %%IF %LOCATION_BLACKLIST_RE%
    # check location_blacklist_re
    %%CSV %LOCATION_BLACKLIST_RE%
    location ~* "%0%" {
      %NGINX_ACTION_ABORT%;
    }
    %%ENDCSV
    %%ELSE
    # no location_blacklist_re
    %%ENDIF

    %%IF %REFERER_BLACKLIST_RE%
    # check referer_blacklist_re
    %%CSV %REFERER_BLACKLIST_RE%
    if ( $http_referer ~* "%0%" ) {
      %NGINX_ACTION_ABORT%;
    }
    %%ENDCSV
    %%ELSE
    # no referer_blacklist_re
    %%ENDIF

    # whitelists

    %%IF %USER_AGENT_WHITELIST_RE%
    # check user_agent_whitelist_re
    set $non_whitelist_user_agent 1;
    %%CSV %USER_AGENT_WHITELIST_RE%
    if ( $http_user_agent ~* "%0%" ) {
      set $non_whitelist_user_agent 0;
    }
    %%ENDCSV
    %%ELSE
    # no user_agent_whitelist_re
    %%ENDIF

    %%IF %LOCATION_WHITELIST_RE%
    # check location_whitelist_re
    set $non_whitelist_location 1;
    %%CSV %LOCATION_WHITELIST_RE%
    location ~* "%0%" {
      set $non_whitelist_location 0;
    }
    %%ENDCSV
    %%ELSE
    # no location_whitelist_re
    %%ENDIF

    %%IF %REFERER_WHITELIST_RE%
    # check referer_whitelist_re
    set $non_whitelist_referer 1;
    %%CSV %REFERER_WHITELIST_RE%
    if ( $http_referer ~* "%0%" ) {
      set $non_whitelist_referer 0;
    }
    %%ENDCSV
    %%ELSE
    # no referer_whitelist_re
    %%ENDIF

    # for traffic
    location / {
      %%IF %USER_AGENT_WHITELIST_RE%
      # check success of user_agent_whitelist_re
      if ( $non_whitelist_user_agent ) {
        %NGINX_ACTION_ABORT%;
      }
      %%ELSE
      # no check for success of user_agent_whitelist_re
      %%ENDIF

      %%IF %LOCATION_WHITELIST_RE%
      # check success of location_whitelist_re
      if ( $non_whitelist_location ) {
        %NGINX_ACTION_ABORT%;
      }
      %%ELSE
      # no check for success of location_whitelist_re
      %%ENDIF

      %%IF %REFERER_WHITELIST_RE%
      # check success of referer_whitelist_re
      if ( $non_whitelist_referer ) {
        %NGINX_ACTION_ABORT%;
      }
      %%ELSE
      # no check for success of referer_whitelist_re
      %%ENDIF

      %%IF %COOKIE_LOCK%
      # check for cookie-lock
      if ( $cookie_eotk_lock != "%COOKIE_LOCK%" ) {
        %NGINX_ACTION_ABORT%;
      }
      %%ELSE
      # no cookie lock checks
      %%ENDIF

      proxy_pass "$scheme://${servernamesubdomain}%DNS_DOMAIN%"; # note $scheme
      proxy_http_version 1.1;

      # a note on proxy_set_header, add_header, similar methods, etc;
      # if you override *any* header then you will lose the other
      # headers inherited from the parent contexts:
      # https://blog.g3rt.nl/nginx-add_header-pitfall.html

      proxy_set_header X-From-Onion %X_FROM_ONION_VALUE%;
      proxy_set_header Host "${servernamesubdomain}%DNS_DOMAIN%";
      proxy_set_header Accept-Encoding "identity";
      proxy_set_header Connection $connection_upgrade; # SSL
      proxy_set_header Upgrade $http_upgrade; # SSL
      proxy_ssl_server_name on; # SSL

      # rewrite request referer
      set_by_lua_block $referer2 { return onion_to_dns(ngx.var.http_referer) }
      proxy_set_header Referer $referer2;

      # rewrite request origin
      set_by_lua_block $origin2 { return onion_to_dns(ngx.var.http_origin) }
      proxy_set_header Origin $origin2;

      %%IF %SUPPRESS_METHODS_EXCEPT_GET%
      # suppress non-GET methods (e.g.: POST)
      limit_except GET {
        deny all;
      }
      %%ELSE
      # non-GET methods (e.g.: POST) are not suppressed
      %%ENDIF
    }
  }

  %%END

  # header purge
  more_clear_headers "Age";
  more_clear_headers "Server";
  more_clear_headers "Via";
  more_clear_headers "X-From-Nginx";
  more_clear_headers "X-NA";
  more_clear_headers "X-Powered-By";
  more_clear_headers "X-Request-Id";
  more_clear_headers "X-Runtime";
  more_clear_headers "X-Varnish";
}
